#include "Fraction.h"

Fraction::Fraction(const int n, const int d) : numerator(n), denominator(d)
{
	if (numerator)
	{
		int gcd = YADCOMB_gcd(numerator, denominator);

		if (denominator < 0)
		{
			numerator /= -gcd;
			denominator /= -gcd;
		}
		else
		{
			numerator /= gcd;
			denominator /= gcd;
		}
	}
	else
	{
		denominator = 1;
	}
}

int Fraction::get_numerator() const
{
	return numerator;
}

int Fraction::get_denominator() const
{
	return denominator;
}

Fraction operator-(const Fraction& rhs)
{
	return Fraction(-rhs.get_numerator(), rhs.get_denominator());
}

Fraction Fraction::operator+(const Fraction& rhs) const
{
    int gcd = YADCOMB_gcd(denominator, rhs.denominator);
    int d = denominator / gcd;
    int n = numerator * (rhs.denominator / gcd) + rhs.numerator * d;
	gcd = YADCOMB_gcd(n, gcd);
	return Fraction(n / gcd, d * rhs.denominator / gcd);
}

Fraction Fraction::operator-(const Fraction& rhs) const
{
    int gcd = YADCOMB_gcd(denominator, rhs.denominator);
    int d = denominator / gcd;
    int n = numerator * (rhs.denominator / gcd) - rhs.numerator * d;
	gcd = YADCOMB_gcd(n, gcd);
	return Fraction(n / gcd, d * rhs.denominator / gcd);
}

Fraction Fraction::operator*(const Fraction& rhs) const
{
	int gcd1 = YADCOMB_gcd(numerator, rhs.denominator);
	int gcd2 = YADCOMB_gcd(rhs.numerator, denominator);
	return Fraction((numerator / gcd1) * (rhs.numerator / gcd2), (denominator / gcd2) * (rhs.denominator / gcd1));
}

Fraction Fraction::operator/(const Fraction& rhs) const
{
	int gcd1 = YADCOMB_gcd(numerator, rhs.numerator);
	int gcd2 = YADCOMB_gcd(rhs.denominator, denominator);
	return Fraction((numerator / gcd1) * (rhs.denominator / gcd2), (denominator / gcd2) * (rhs.numerator / gcd1));
}

std::ostream& operator<<(std::ostream& os, const Fraction& f)
{
	return os << f.get_numerator() << ':' << f.get_denominator();
}
